<?php
class NerdPass_Data {
	public static $db;
	private static $users;
	private static $categories;
	public static $log;
	
	/* Initiate database connection and create schema if first run */
	public static function factory() {
		if (!file_exists('../application/data/nerdpass.sq3')) $ct = true;
		
		if (self::$db == NULL) {
			self::$db = Zend_Db::factory('Pdo_Sqlite', array('dbname' => '../application/data/nerdpass.sq3'));
			self::$db->setFetchMode(Zend_Db::FETCH_ASSOC);
		}
		
		if (isset($ct) && $ct == true) {
			// Create table schema
			$tables = array(
				"CREATE TABLE users (username, tokenid, apiid, signaturekey, role, keytest)",
				"CREATE TABLE passwords (uid INTEGER PRIMARY KEY AUTOINCREMENT, username, category, summary, myusername, password, website, notes, access)",
				"CREATE TABLE categories (username, uid INTEGER PRIMARY KEY AUTOINCREMENT, category)",
				"CREATE TABLE logs (timestamp, message, priority, priorityName)",
			);
			foreach ($tables as $table) {
				//NerdPass_Data::$log->info("Creating the database for the first time.");
				self::$db->query($table);
			}
			
		}
		
		/* Setup logging */
		$columnmap = array(
			'timestamp' => 'timestamp',
			'message' => 'message',
			'priority' => 'priority',
			'priorityName' => 'priorityName',
		);
		$writer = new Zend_Log_Writer_Db(self::$db, 'logs', $columnmap);
		self::$log = new Zend_Log($writer);
		
		if (isset($ct) && $ct == true) self::addUser('admin', 'letmein', '1834', '5pgoeSqcxvT+lJzkfoVonB7V7U8=', 'hurcdvjbrkbibbedgleetjuntdecebhnktkbcvdgdkbh', 'admin');
	}
	
	/* Add user */
	public static function addUser($username, $password, $apiid, $sigkey, $otp, $role) {
		NerdPass_Data::$log->info("User '$username' is being added to NerdPass.");
		
		// Create a key for this user
		$userkey = NerdPass_Secure::create_key($otp);
		
		// Compile keytest and encrypt it for storage
		$keytest = $username . $userkey;
		$ns = new NerdPass_Secure($password, $username);
		$ekeytest = $ns->encrypt($keytest);
		
		// Get token ID
		$tokenid = md5(substr($otp, 0, 12));
		
		// Write data to database
		$data = array(
			'username' => $username,
			'tokenid' => $tokenid,
			'apiid' => $apiid,
			'signaturekey' => $sigkey,
			'role' => $role,
			'keytest' => $ekeytest
		);
		self::$db->insert('users', $data);
	}
	
	public static function deleteUser()
	{
		$auth = Zend_Auth::getInstance();
		$username = $auth->getIdentity();
		$username = self::$db->quote($username);
		
		NerdPass_Data::$log->info("User '$username' is being removed from NerdPass.");
		self::$db->delete('users', "username = $username");
	}
	
	/* Fetch user row as array and return user information */
	public static function getUser($username) {
		if (isset(self::$users[$username])) {
			return self::$users[$username];
		}
		
		$row = self::$db->fetchRow("SELECT * FROM users WHERE username = ?", $username);
		if (count($row) < 1) {
			return false;
		}
		self::$users[$row['username']] = $row;
		return $row;
	}
	
	/* Add a category to database */
	public static function addCategory($category) {
		$auth = Zend_Auth::getInstance();
		$data = array(
			'username' => $auth->getIdentity(),
			'category' => $category
		);
		NerdPass_Data::$log->info("'" . $auth->getIdentity() . "' has added a new category called $category");
		self::$db->insert('categories', $data);
	}
	
	/* Get array of categories for user */
	public static function getCategories() {
		if (isset(self::$categories)) {
			return self::$categories;
		}
		$auth = Zend_Auth::getInstance();
		self::$categories = self::$db->fetchAll("SELECT * FROM categories WHERE username = ?", $auth->getIdentity());
		return self::$categories;
	}
	
	/* Delete category */
	public static function deleteCategory($uid) {
		$uid = self::$db->quote($uid);
		NerdPass_Data::$log->info("Category with uid $uid has been removed.");
		self::$db->delete('categories', "uid = $uid");
	}
	
	/* Get passwords */
	public static function getPasswords($category = NULL) {
		$auth = Zend_Auth::getInstance();
		$where = array($auth->getIdentity());
		$sql = "SELECT uid,category,summary FROM passwords WHERE username = ?";
		if ($category != NULL) {
			$sql .= " WHERE category = ?";
			$where[] = $category;
		}
		NerdPass_Data::$log->info("Passwords fetched for " . $auth->getIdentity());
		$rows = self::$db->fetchAll($sql, $where);
		$organized = array();
		foreach ($rows as $row) {
			$organized[$row['category']][] = $row;
		}
		return $organized;
	}
	
	/* Fetch a password */
	public static function getPassword($uid) {
		$auth = Zend_Auth::getInstance();
		self::$log->info("User " . $auth->getIdentity() . " fetching password with uid $uid");
		// Make sure the requested password belongs to the user signed in
		$sql = "SELECT * FROM passwords WHERE uid = ?";
		$result = self::$db->fetchRow($sql, $uid);
		if ($result['username'] != $auth->getIdentity()) {
			throw new Zend_Exception('So you thought it would be this easy eh!');
		}
		
		/* Decrypt the data */
		$session = new Zend_Session_Namespace('keys');
		$ns = new NerdPass_Secure(NULL, NULL, $session->key);
		$data['username'] = str_replace("\x0", '', $ns->decrypt($result['myusername']));
		$data['password'] = str_replace("\x0", '', $ns->decrypt($result['password']));
		$data['notes'] = str_replace("\x0", '', $ns->decrypt($result['notes']));
		$data['website'] = str_replace("\x0", '', $ns->decrypt($result['website']));
		$data['summary'] = $result['summary'];
		$data['category'] = $result['category'];
		return $data;
	}
	
	/* Add password to database (username, category, summary, myusername, password, website, notes, access) */
	public static function addPassword($category, $summary, $username, $password, $website, $notes) {
		$auth = Zend_Auth::getInstance();
		NerdPass_Data::$log->info('User ' . $auth->getIdentity() . ' has added a new password to the DB');
		$session = new Zend_Session_Namespace('keys');
		$ns = new NerdPass_Secure(NULL, NULL, $session->key);
		$data = array(
			'username' => $auth->getIdentity(),
			'category' => $category,
			'summary' => $summary,
			'myusername' => $ns->encrypt($username),
			'password' => $ns->encrypt($password),
			'website' => $ns->encrypt($website),
			'notes' => $ns->encrypt($notes),
			'access' => NULL,
		);
		self::$db->insert('passwords', $data);
	}
	
	/* Save changes to password */
	public static function editPassword($uid, $category, $summary, $username, $password, $website, $notes) {
		$auth = Zend_Auth::getInstance();
		NerdPass_Data::$log->info('User ' . $auth->getIdentity() . ' is saving changes to password with UID ' . $uid);
		
		// Verify user can do this
		$sql = "SELECT * FROM passwords WHERE uid = ?";
		$result = self::$db->fetchRow($sql, $uid);
		if ($result['username'] != $auth->getIdentity()) {
			throw new Zend_Exception('So you thought it would be this easy eh!');
		}
		
		// Prepare the data
		$session = new Zend_Session_Namespace('keys');
		$ns = new NerdPass_Secure(NULL, NULL, $session->key);
		$data = array(
			'category' => $category,
			'summary' => $summary,
			'myusername' => $ns->encrypt($username),
			'password' => $ns->encrypt($password),
			'website' => $ns->encrypt($website),
			'notes' => $ns->encrypt($notes),
			'access' => NULL,
		);
		self::$db->update('passwords', $data, 'uid = ' . $result['uid']);
	}
	
	/* Delete a password from the database */
	public static function deletePassword($uid) {
		$auth = Zend_Auth::getInstance();
		NerdPass_Data::$log->info('User ' . $auth->getIdentity() . ' is deleting password with UID ' . $uid);
		
		// Do some verification
		$sql = "SELECT * FROM passwords WHERE uid = ?";
		$result = self::$db->fetchRow($sql, $uid);
		if (!is_array($result) || count($result) <= 0) {
			throw new Zend_Exception('I don\'t think so bud!');
		}
		if ($result['username'] != $auth->getIdentity()) {
			throw new Zend_Exception('So you thought it would be this easy eh!');
		}
		self::$db->delete('passwords', 'uid = ' . $result['uid']);
	}
}